/***************************************************************************
    QRSAGSMapToolExtent.h  -  map tool that emits an extent
    ---------------------
    begin                : July 2017
    copyright            : (C) 2017 by Mathieu Pellerin
    email                : nirvn dot asia at gmail dot com
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#include "qrsagsmaptoolextent.h"
#include "qgsmapcanvas.h"
#include "qgswkbtypes.h"
#include "qgsmapmouseevent.h"
#include "qgsquadrilateral.h"

QRSAGSMapToolExtent::QRSAGSMapToolExtent( QgsMapCanvas *canvas )
    : QgsMapTool( canvas )
{
    mRubberBand.reset( new QgsRubberBand( canvas, QgsWkbTypes::PolygonGeometry ) );
    mRubberBandTemp = new QgsRubberBand( canvas, QgsWkbTypes::PolygonGeometry );
}

void QRSAGSMapToolExtent::activate()
{
    QgsMapTool::activate();
}

void QRSAGSMapToolExtent::deactivate()
{
    mRubberBand->reset( QgsWkbTypes::PolygonGeometry );

    QgsMapTool::deactivate();
}

void QRSAGSMapToolExtent::canvasMoveEvent( QgsMapMouseEvent *e )
{
    if ( !mDraw )
        return;

    QgsPointXY p = toMapCoordinates( e->pos() );
    if ( mRatio.width() > 0 && mRatio.height() > 0 )
    {
        double width = std::fabs( p.x() - mStartPoint.x() );
        double height = width * ( mRatio.width() / mRatio.height() );
        if ( p.y() - mStartPoint.y() < 0 )
            height *= -1;
        p.setY( mStartPoint.y() + height );
    }

    mEndPoint = toMapCoordinates( e->pos() );
    calculateEndPoint( mEndPoint );
    drawExtent();
}

void QRSAGSMapToolExtent::canvasPressEvent( QgsMapMouseEvent *e )
{
    mStartPoint = toMapCoordinates( e->pos() );
    mEndPoint = mStartPoint;
    drawExtent();

    mDraw = true;
}

void QRSAGSMapToolExtent::canvasReleaseEvent( QgsMapMouseEvent *e )
{
    if ( !mDraw )
        return;

    mEndPoint = toMapCoordinates( e->pos() );
    calculateEndPoint( mEndPoint );
    mRubberBand->reset( QgsWkbTypes::PolygonGeometry);
    //当确定范围后，就将之前画的部分清除，同时构建一个固定的场所
    QgsRectangle rect( mStartPoint, mEndPoint );
    mRubberBandTemp->addPoint( QgsPointXY( rect.xMinimum(), rect.yMinimum() ), false );
    mRubberBandTemp->addPoint( QgsPointXY( rect.xMaximum(), rect.yMinimum() ), false );
    mRubberBandTemp->addPoint( QgsPointXY( rect.xMaximum(), rect.yMaximum() ), false );
    mRubberBandTemp->addPoint( QgsPointXY( rect.xMinimum(), rect.yMaximum() ), true );
    QColor extentColor(255,255,255,125);
    mRubberBandTemp->setFillColor(extentColor);
    QColor strokeColor(50,50,50,255);
    mRubberBandTemp->setStrokeColor(strokeColor);

    emit extentChanged( extent() );

    mDraw = false;
}

QgsRectangle QRSAGSMapToolExtent::extent() const
{
    if ( mStartPoint.x() != mEndPoint.x() && mStartPoint.y() != mEndPoint.y() )
    {
        return QgsRectangle( mStartPoint, mEndPoint );
    }
    else
    {
        return QgsRectangle();
    }
}

void QRSAGSMapToolExtent::clearRubberBand()
{
    if(mRubberBandTemp != nullptr){
        mRubberBandTemp->reset(QgsWkbTypes::PolygonGeometry);
    }
}

void QRSAGSMapToolExtent::calculateEndPoint( QgsPointXY &point )
{
    if ( mRatio.width() > 0 && mRatio.height() > 0 )
    {
        double width = std::fabs( point.x() - mStartPoint.x() );
        double height = width * mRatio.height() / mRatio.width();
        if ( point.y() - mStartPoint.y() < 0 )
            height *= -1;
        point.setY( mStartPoint.y() + height );
    }
}

void QRSAGSMapToolExtent::drawExtent()
{

    if ( qgsDoubleNear( mStartPoint.x(), mEndPoint.x() ) && qgsDoubleNear( mStartPoint.y(), mEndPoint.y() ) )
        return;

    mRubberBand->reset( QgsWkbTypes::PolygonGeometry );

    QgsRectangle rect( mStartPoint, mEndPoint );

    mRubberBand->reset( QgsWkbTypes::PolygonGeometry );
    mRubberBand->addPoint( QgsPointXY( rect.xMinimum(), rect.yMinimum() ), false );
    mRubberBand->addPoint( QgsPointXY( rect.xMaximum(), rect.yMinimum() ), false );
    mRubberBand->addPoint( QgsPointXY( rect.xMaximum(), rect.yMaximum() ), false );
    mRubberBand->addPoint( QgsPointXY( rect.xMinimum(), rect.yMaximum() ), true );
    QColor extentColor(255,255,255,125);
    mRubberBand->setFillColor(extentColor);
    QColor strokeColor(50,50,50,255);
    mRubberBand->setStrokeColor(strokeColor);
    mRubberBand->show();
}
